package com.xiran.srpingboottemplateself.filter;

import com.xiran.srpingboottemplateself.util.JwtTokenHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private static final String AUTH_HEADER = "Authorization";
    private static final String TOKEN_PREFIX = "Bearer ";

    private final JwtTokenHelper jwtTokenHelper;
    private final UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {

        try {
            String authHeader = request.getHeader(AUTH_HEADER);
            log.debug("请求路径: {}, Authorization头: {}", request.getRequestURI(), authHeader);

            if (authHeader != null && authHeader.startsWith(TOKEN_PREFIX)) {
                String jwtToken = authHeader.substring(TOKEN_PREFIX.length());
                log.debug("提取的JWT Token: {}", jwtToken.substring(0, Math.min(20, jwtToken.length())) + "...");

                if (jwtToken != null && !jwtToken.trim().isEmpty()) {
                    // 解析 Token 获取用户名
                    String username = jwtTokenHelper.parseToken(jwtToken).getBody().getSubject();
                    log.debug("从Token中解析出的用户名: {}", username);

                    if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                        // 加载用户详情
                        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                        log.debug("加载的用户详情: {}, 权限: {}", userDetails.getUsername(), userDetails.getAuthorities());

                        // 创建认证令牌
                        UsernamePasswordAuthenticationToken authentication =
                                new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

                        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                        // 设置安全上下文
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                        log.debug("为用户 [{}] 设置安全上下文成功", username);
                    } else {
                        log.debug("用户名为空或已存在认证上下文");
                    }
                } else {
                    log.debug("JWT Token为空或空白");
                }
            } else {
                log.debug("Authorization头为空或不以Bearer开头");
            }
        } catch (Exception e) {
            log.error("JWT 认证过程中发生错误: {}", e.getMessage(), e);
            // 继续执行过滤器链，后续的权限校验会处理认证失败
        }

        filterChain.doFilter(request, response);
    }
}